package smtp;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;

import javax.mail.Folder;
import javax.mail.MessagingException;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPMessage;

/**
 * JPanel containing a list of messages and buttons to perform operations on them
 * 
 * @author chandlerr, liw, wendlandts
 *
 */
public class MessagesListViewer extends JPanel {

	// listeners to be notified when a list item is clicked
	// (i.e. when a message is requested to be opened)
	LinkedList<ActionListener> openMessageListeners;
	
	// JList containing the current page of messages
	JMessageList messageList;
	
	// Listens for a new folder request
	ActionListener newFolderListener;
	
	// To navigate to previous page of messages
	final JButton prevButton;
	// To navigate to next page of messages
	final JButton nextButton;
	
	// Displays current and total page numbers
	JLabel pageLabel;

	// navigation toolbar
	JToolBar navToolbar;

	/**
	 * Constructor
	 * @param f - folder of which to view contents
	 */
	public MessagesListViewer (IMAPFolder f){
		openMessageListeners = new LinkedList<ActionListener>();
		newFolderListener = null;

		messageList = new JMessageList(f);
		JScrollPane scrollPane = new JScrollPane(messageList);

		// listen for selection changes from the JList and notify the openMessageListeners
		messageList.addListSelectionListener(new ListSelectionListener(){

			@Override
			public void valueChanged(ListSelectionEvent event) {
				if(!event.getValueIsAdjusting()){
					if (messageList.getSelectedValue() != null){
						ActionEvent e = new ActionEvent(messageList.getSelectedValue(), event.getFirstIndex(), "Select Message");
						for (ActionListener l: openMessageListeners){
							l.actionPerformed(e);
						}
					}
				}
			}

		});

		// NAGIVATE BUTTONS
		prevButton = new JButton("PREV");
		nextButton = new JButton("NEXT");
		pageLabel = new JLabel(){
			// override set text so that when a null is passed in, it updates the information
			// Page <currentPage> of <totalPages>
			public void setText (String x){
				if(x != null){
					super.setText(x);
				}else{
					if (messageList.getModel().getClass() == MessageListModel.class){
						MessageListModel mlm = (MessageListModel)(messageList.getModel());
						this.setText("Page " + mlm.getPage() + " of " + mlm.getTotalPages());
					}
				}
			}
		};
		makeNavButtons();

		navToolbar = new JToolBar();
		navToolbar.setFloatable(false);
		FlowLayout fl = new FlowLayout();
		fl.setAlignment(FlowLayout.CENTER);
		navToolbar.setLayout(fl);
		navToolbar.add(prevButton);
		navToolbar.add(pageLabel);
		navToolbar.add(nextButton);

		// MESSAGE OP PANEL: DELETE, MARK READ
		JPanel messageOpPanel = new JPanel();
		messageOpPanel.setLayout(new GridLayout(1,3));
		messageOpPanel.add(new JButton("Delete"));
		messageOpPanel.add(new JButton("Mark Unread"));

		// Another framing panel to make room for another row of buttons
		JPanel inner = new JPanel();
		inner.setLayout(new BorderLayout());
		JLabel messageListLable = new JLabel("Message List Title");
		inner.add(messageListLable, BorderLayout.NORTH);
		inner.add(scrollPane, BorderLayout.CENTER);
		inner.add(messageOpPanel, BorderLayout.SOUTH); // add delete, mark unread

		setLayout(new BorderLayout());
		add(inner, BorderLayout.CENTER);
		add(navToolbar, BorderLayout.SOUTH);
	}

	/**
	 * Adds listener for open message notifications
	 * @param l - listener
	 */
	public void addMessageSelectedListener (ActionListener l){
		openMessageListeners.add(l);
	}

	/**
	 * Get the selected message in the JList
	 * If none are selected, get the first message
	 * if none exist, return null
	 * 
	 * @return - a default message (ideally to display)
	 */
	public IMAPMessage getDefaultMessage(){
		Object selected = messageList.getSelectedValue();
		IMAPMessage message = null;

		if ((selected != null) && (selected.getClass() == IMAPMessage.class)){
			message = (IMAPMessage)selected;
		} else if ((selected = messageList.getModel().getElementAt(0)).getClass() == IMAPMessage.class){
			message = (IMAPMessage) selected;
		}
		return message;
	}

	/**
	 * Gets a listener to act on folder update requests
	 * 
	 * @return - listener
	 */
	public ActionListener getChangeFolderListener(){
		if (newFolderListener == null){
			newFolderListener = new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent e) {
					if(e.getSource().getClass() == IMAPFolder.class){
						messageList.changeFolder((IMAPFolder) e.getSource());
					}

				}

			};
		}
		return newFolderListener;
	}


	/**
	 * Changes the current folder to the folder indicated
	 * 
	 * @param f - new folder
	 */
	public void changeFolder(Folder f){
		if(f.getClass() == IMAPFolder.class){
			messageList.changeFolder((IMAPFolder) f);
		}
		nextButton.setEnabled(messageList.hasNext());
		prevButton.setEnabled(messageList.hasPrev());
		pageLabel.setText(null);
	}

	/**
	 * Constructs the next and previous navigation buttons
	 */
	private void makeNavButtons(){
		prevButton.setActionCommand("prev");
		nextButton.setActionCommand("next");

		nextButton.setEnabled(messageList.hasNext());
		prevButton.setEnabled(messageList.hasPrev());
		pageLabel.setText(null);

		ActionListener navListener = new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				if (e.getActionCommand().equals("prev")){
					try {
						prevButton.setEnabled(messageList.prev());
						nextButton.setEnabled(messageList.hasNext());
						pageLabel.setText(null); // updates the page number display

					} catch (MessagingException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				} else if (e.getActionCommand().equals("next")){
					try {
						nextButton.setEnabled(messageList.next());
						prevButton.setEnabled(messageList.hasPrev());
						pageLabel.setText(null); // updates the page number display
						
					} catch (MessagingException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
			}

		};

		prevButton.addActionListener(navListener);
		nextButton.addActionListener(navListener);
	}

}
